package person

import (
	"database/sql"
	"dcx.com/miyula/homework/p1/week2/model"
	"github.com/jinzhu/gorm"
	"github.com/pkg/errors"
)

type Service interface {

	// 获得单个人员数据，如果找不到数据，需要抛出错误
	FetchOneByID(id uint32) (*model.Person, error)
	// 获得完整的人员数据列表，如果列表为空，不抛出错误
	FetchAll() ([]model.Person, error)
	// 获得完整的人员数据列表，如果列表为空，抛出Empty错误
	FetchAllAndCheckEmpty() ([]model.Person, error)
}

func NewService(db *gorm.DB) (Service) {
	return &service {
		db: db,
	}
}

type service struct {
	db *gorm.DB
}

func (s *service) FetchOneByID(id uint32) (*model.Person, error) {

	var (
		tx = s.db
		data model.Person
	)

	if err:= tx.Raw(`SELECT * FROM person where id = ? ORDER BY id DESC LIMIT 1`, id).Scan(&data).Error; err != nil {
		return nil, errors.Wrap(err, "service.person.FetchOneByID")
	}

	return &data, nil
}

func (s *service) FetchAll() ([]model.Person, error) {
	var (
		tx = s.db
		list []model.Person
	)

	if err := tx.Model(model.Person{}).Order("id DESC").Scan(&list).Error; err!= nil {
		if errors.Is(err, sql.ErrNoRows) {
			// 说明：由于gorm的设置，本身这种情况下就是不报错的，只是在这里写个理论上不可能执行到的代码，说明错误处理的逻辑
			// 没有找到记录的情况下，返回空数组，不需要抛出异常
			return []model.Person{}, nil
		}
		return nil, errors.Wrap(err, "service.person.FetchAll")
	}
	return list, nil
}

func (s *service) FetchAllAndCheckEmpty() ([]model.Person, error) {
	var (
		tx = s.db
		list []model.Person
	)

	if err := tx.Model(model.Person{}).Order("id DESC").Scan(&list).Error; err!= nil {
		return nil, errors.Wrap(err, "service.person.FetchAllAndCheckEmpty")
	}

	if len(list) == 0 {
		return nil, errors.New("service.person.FetchAllAndCheckEmpty 返回数据为空")
	}

	return list, nil
}